package com.xinchili.autoddl.autoClass.processor;


import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xinchili.autoddl.autoClass.properties.EntityScanProperties;
import com.xinchili.autoddl.autoClass.strategy.ColumnCommentResolver;
import com.xinchili.autoddl.autoClass.strategy.ColumnNameResolver;
import com.xinchili.autoddl.autoClass.strategy.ColumnTypeResolver;
import com.xinchili.autoddl.autoClass.strategy.TableCommentResolver;
import com.xinchili.autoddl.autoClass.util.JdbcUtils;
import com.xinchili.autoddl.autoClass.util.ReflectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class EntityProcessor {

    private final ColumnNameResolver columnNameResolver;
    private final ColumnTypeResolver columnTypeResolver;
    private final TableCommentResolver tableCommentResolver;
    private final ColumnCommentResolver columnCommentResolver;
    private final EntityScanProperties entityScanProperties;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public EntityProcessor(
            ColumnNameResolver columnNameResolver,
            ColumnTypeResolver columnTypeResolver,
            TableCommentResolver tableCommentResolver,
            ColumnCommentResolver columnCommentResolver,
            EntityScanProperties entityScanProperties) {
        this.columnNameResolver = columnNameResolver;
        this.columnTypeResolver = columnTypeResolver;
        this.tableCommentResolver = tableCommentResolver;
        this.entityScanProperties = entityScanProperties;
        this.columnCommentResolver = columnCommentResolver;
    }

    @PostConstruct
    public void init() {
        // 示例：扫描包路径下所有带有 @TableName 的类
        List<String> packages = entityScanProperties.getTablePackage();
        System.out.println("打印--------------------------");

        Set<Class<?>> entityClasses = ReflectionUtils.scanClassesWithAnnotation(packages, TableName.class);
        System.out.println("扫描到的实体类数量: " + entityClasses.size());
        for (Class<?> clazz : entityClasses) {
            processEntityClass(clazz);
        }
    }

    public void processEntityClass(Class<?> clazz) {
        TableName anno = clazz.getAnnotation(TableName.class);
        if (anno == null) return;

        String tableName = anno.value();
        if (!JdbcUtils.tableExists(jdbcTemplate, tableName)) {
            createTable(tableName, clazz);
        } else {
            alterTable(tableName, clazz);
        }
    }

    private void createTable(String tableName, Class<?> clazz) {
        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append("CREATE TABLE ").append(tableName).append(" (");

        List<Field> fields = ReflectionUtils.getAllFields(clazz);
        for (Field field : fields) {
            String columnName = columnNameResolver.resolveColumnName(field);
            if (columnName == null) continue;

            String columnType = columnTypeResolver.resolveColumnType(field);
            String columnComment = columnCommentResolver.resolveColumnComment(field);

            sqlBuilder.append(columnName).append(" ").append(columnType);

            if (field.isAnnotationPresent(TableId.class)) {
                // 判断是否是主键（可扩展）
                sqlBuilder.append(" PRIMARY KEY");
            }

            if (!columnComment.isEmpty()) {
                sqlBuilder.append(" COMMENT '").append(columnComment).append("'");
            }

            sqlBuilder.append(", ");
        }

        if (sqlBuilder.toString().endsWith(", ")) {
            sqlBuilder.setLength(sqlBuilder.length() - 2); // 去掉最后的逗号空格
        }

        String tableComment = tableCommentResolver.resolveTableComment(clazz);
        sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC");
        if (!tableComment.isEmpty()) {
            sqlBuilder.append(" COMMENT='").append(tableComment).append("'");
        }
        sqlBuilder.append(";");

        jdbcTemplate.execute(sqlBuilder.toString());
        System.out.println("已创建表: " + tableName + "\nSQL: " + sqlBuilder);
    }


    private void alterTable(String tableName, Class<?> clazz) {
        Set<String> dbColumns = JdbcUtils.getTableColumns(jdbcTemplate, tableName);
        Map<String, String> dbColumnTypes = JdbcUtils.getColumnTypes(jdbcTemplate, tableName);
        Map<String, String> dbColumnComments = JdbcUtils.getColumnComments(jdbcTemplate, tableName);

        List<Field> fields = ReflectionUtils.getAllFields(clazz);
        for (Field field : fields) {
            String columnName = columnNameResolver.resolveColumnName(field);
            if (columnName == null) continue;

            String expectedType = columnTypeResolver.resolveColumnType(field);
            String expectedComment = columnCommentResolver.resolveColumnComment(field);

            if (!dbColumns.contains(columnName.toLowerCase())) {
                // 新增字段
                String addSql = String.format(
                        "ALTER TABLE %s ADD COLUMN %s %s COMMENT '%s';",
                        tableName, columnName, expectedType, expectedComment
                );
                jdbcTemplate.execute(addSql);
                System.out.println("新增字段: " + columnName + " in " + tableName);
            } else {
                // 字段存在，检查类型和注释
                String actualType = dbColumnTypes.getOrDefault(columnName.toUpperCase(), "");
                String actualComment = dbColumnComments.getOrDefault(columnName.toUpperCase(), "");

                boolean typeMismatch = !expectedType.equalsIgnoreCase(actualType);
                boolean commentMismatch = !expectedComment.equals(actualComment);

                if (typeMismatch || commentMismatch) {
                    String modifySql = String.format(
                            "ALTER TABLE %s MODIFY COLUMN %s %s COMMENT '%s';",
                            tableName, columnName, expectedType, expectedComment
                    );
                    jdbcTemplate.execute(modifySql);
                    System.out.println("修改字段: " + columnName + " in " + tableName);
                }
            }
        }
    }

}
